﻿// 103最大半连通子图.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>

using  namespace std;

/*


http://oj.daimayuan.top/course/23/problem/945
一个有向图G=(V,E)称为半连通的，如果满足：∀u,v∈V，满足u→v或v→u，即对于图中任意两点u，v，
存在一条u到v的有向路径或者从v到u的有向路径。

若G′=(V′,E′)满足V′⊂V，E′是E中所有跟V′有关的边，则称G′是G的一个导出子图。若G′是G的导出子图，
且G′半连通，则称G′为G的半连通子图。

若G′是G所有半连通子图中包含节点数最多的，则称G′是G的最大半连通子图。给定一个有向图G，
请求出G的最大半连通子图拥有的节点数K，以及不同的最大半连通子图的数目C。由于C可能比较大，仅要求输出C对X的余数。

输入格式
第一行包含三个整数N,M,X。N,M分别表示图G的点数与边数，X的意义如上文所述。

接下来M行，每行两个正整数a,b(1≤a,b≤N)，表示一条有向边(a,b)。

保证输入中没有重边，N≤105,M≤106,X≤108。

输出格式
一共两行，第一行包含一个整数K，第二行包含整数CmodX。

样例输入
6 6 20070603
1 2
2 1
1 3
2 4
5 6
6 4
样例输出
3
3
*/


/*
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 101000;
vector<int> e[N];

int n, m, mod, cnt;

int dfn[N], low[N], ins[N], bel[N], idx;
stack<int> stk;
vector<int> vec[N];
int dp[N], way[N], vis[N], T, ans, w;

void dfs(int u) {
	dfn[u] = low[u] = ++idx;
	ins[u] = true;
	stk.push(u);
	for (auto v : e[u]) {
		if (!dfn[v]) dfs(v);
		if (ins[v]) low[u] = min(low[u], low[v]);
	}
	if (dfn[u] == low[u]) {
		++cnt;
		int sz = 0;
		dp[cnt] = 0;
		way[cnt] = 1;
		++T;
		vis[cnt] = T;
		while (true) {
			int v = stk.top();
			ins[v] = false;
			bel[v] = cnt;
			sz++;
			for (int w : e[v]) if (vis[bel[w]] != T && bel[w] != 0) {
				vis[bel[w]] = T;
				if (dp[bel[w]] > dp[cnt]) {
					dp[cnt] = dp[bel[w]];
					way[cnt] = 0;
				}
				if (dp[bel[w]] == dp[cnt]) {
					way[cnt] = (way[cnt] + way[bel[w]]) % mod;
				}
			}
			stk.pop();
			if (v == u) break;
		}
		dp[cnt] += sz;
		if (dp[cnt] > ans) ans = dp[cnt], w = 0;
		if (dp[cnt] == ans) w = (w + way[cnt]) % mod;
	}
}

int main() {
	scanf("%d%d%d", &n, &m, &mod);
	for (int i = 0; i < m; i++) {
		int u, v;
		scanf("%d%d", &u, &v);
		e[u].push_back(v);
	}
	for (int i = 1; i <= n; i++)
		if (!dfn[i]) dfs(i);
	printf("%d\n%d\n", ans, w);
}

*/

int main()
{
    std::cout << "Hello World!\n";
}

 